import {
  createElement,
  ReactElement,
  useEffect,
  useState,
} from 'react';

import { View } from '@tarojs/components';
import models, { WrapModel } from '@/models';
import { handleUserRouterError } from '@/utils';
import { CommunicationModel } from '@/models/communication';

export function useCommunication() {
  return [models.communication] as const;
}


type IWithCommunicationOptions = {
  /** 自动获取通信信息 */
  auto?: boolean;
  /** 兜底组件 */
  fallback?: ReactElement;
  /** 是否注入全局状态 */
  inject?: boolean;
  /** 钩子 */
  hooks?: {
    before?: () => void;
    after?: () => void;
  };
};

export type IWithCommunicationProps<P = {}> = P & {
  communication: CommunicationModel
};

export function withCommunication(options?: IWithCommunicationOptions) {
  const { auto, fallback, inject = true, hooks = {} } = options ?? {};

  return function (Component: any) {
    const WrappedComponent = (props: any) => {
      const [inited, setInited] = useState(false);
      const [communication] = useCommunication();

      useEffect(() => {
        const fn = async () => {
          if (auto && (!communication.communicationInfo || !communication.communicationLetterInfo)) {
            hooks?.before?.();
            try {
              await communication.getCommunicationInfo()
              setInited(true);
            } catch (err) {
              handleUserRouterError(err);
            } finally {
              hooks?.after?.();
            }
          } else {
            setInited(true);
          }
        };

        fn();
      }, []);

      if (!inited) {
        return fallback ?? createElement(View, { className: 'no-communication' });
      }

      return createElement(inject ? WrapModel(Component) : Component, {
        ...props,
        communication
      });
    };

    return WrapModel(WrappedComponent);
  };
}

